providers.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. "use client";
  2. import Sidebar from "@/components/Layout/Sidebar";
  3. import Loading from "@/components/Loading";
  4. import { useSystemStore } from "@/stores/useSystemStore";
  5. import { setHtmlFontSize } from "@/utils";
  6. import { ConfigProvider, Dialog } from "antd-mobile";
  7. import enUS from "antd-mobile/es/locales/en-US";
  8. import { useLocale } from "next-intl";
  9. import { ThemeProviderProps } from "next-themes/dist/types";
  10. import { ReactNode, useLayoutEffect, useRef } from "react";
  11. import { Swiper, SwiperClass, SwiperSlide } from "swiper/react";
  12. import { useDebounceEffect } from "ahooks";
  13. import { initializeApp } from "firebase/app";
  14. import { getMessaging, getToken, onMessage } from "firebase/messaging";
  15. export interface ProvidersProps {
  16. children: ReactNode;
  17. themeProps?: Omit<ThemeProviderProps, "children">;
  18. }
  19. const initFirebase = () => {
  20. // 是否是https
  21. if (document.location.protocol.indexOf("https") === -1) return;
  22. // 浏览器是否支持 且是 pwa
  23. if (!window.Notification) {
  24. Dialog.alert({
  25. getContainer: null,
  26. bodyStyle: { background: "#fff" },
  27. title: "提示",
  28. confirmText: "我知道了",
  29. content: (
  30. <>
  31. <div className={"text-center"}>
  32. <p>当前版本浏览器不支持通知</p>
  33. <p>请更换或升级浏览器获得更好使用体验</p>
  34. </div>
  35. </>
  36. ),
  37. });
  38. return;
  39. }
  40. // 是否开启通知
  41. // new Notification("这是标题", {
  42. // body: "这是正文",
  43. // icon: "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
  44. // requireInteraction: true,
  45. // image: "https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png",
  46. // });
  47. if (Notification.permission === "default") {
  48. // 征求用户的许可
  49. Notification.requestPermission();
  50. }
  51. if (Notification.permission === "denied") return;
  52. const app = initializeApp({
  53. apiKey: process.env.NEXT_PUBLIC_FIREBASE_APIKEY,
  54. authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTHDOMAIN,
  55. projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECTID,
  56. storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGEBUCKET,
  57. messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGINGSENDERID,
  58. appId: process.env.NEXT_PUBLIC_FIREBASE_APPID,
  59. measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENTID,
  60. });
  61. const messaging = getMessaging(app);
  62. // 针对单机测试,或者服务端需要使用这个key可以放开
  63. // if (process.env.NODE_ENV === "development") {
  64. getToken(messaging, {
  65. vapidKey: process.env.NEXT_PUBLIC_FIREBASE_KEYS,
  66. }).then((res) => {
  67. console.log(`🚀🚀🚀🚀🚀-> `, res);
  68. });
  69. // }
  70. onMessage(messaging, (payload) => {
  71. const notifica = new Notification(payload.data?.title || "", {
  72. body: payload.data?.body,
  73. icon: payload.data?.image,
  74. ...payload.data,
  75. });
  76. });
  77. };
  78. const Layout = ({ children, themeProps }: ProvidersProps) => {
  79. const { isCollapse, setCollapse } = useSystemStore((state) => ({
  80. isCollapse: state.isCollapse,
  81. setCollapse: state.setCollapse,
  82. }));
  83. const local = useLocale();
  84. const swiperRef = useRef<SwiperClass>();
  85. const homeContainerRef = useRef<HTMLDivElement>(null);
  86. const startHandler = () => {
  87. homeContainerRef.current?.classList.add("containerMask");
  88. setCollapse(true);
  89. };
  90. const endHandler = () => {
  91. homeContainerRef.current?.classList.remove("containerMask");
  92. setCollapse(false);
  93. };
  94. useLayoutEffect(() => {
  95. // 调用响应式方法
  96. setHtmlFontSize();
  97. }, []);
  98. return (
  99. <div id="app" className="bg-black">
  100. <Swiper
  101. resistanceRatio={10}
  102. initialSlide={2}
  103. slidesPerView={"auto"}
  104. onSlidePrevTransitionStart={startHandler}
  105. onSlideNextTransitionEnd={endHandler}
  106. slideToClickedSlide
  107. onSwiper={(swiper) => {
  108. swiperRef.current = swiper;
  109. }}
  110. allowTouchMove={false}
  111. >
  112. <SwiperSlide>
  113. <section className="relative flex h-[100vh] items-center justify-center">
  114. <Loading />
  115. </section>
  116. </SwiperSlide>
  117. <SwiperSlide style={{ width: "70%" }} className={"bg-[rgb(31,31,31)]"}>
  118. <section className="relative h-[100vh]">{<Sidebar></Sidebar>}</section>
  119. </SwiperSlide>
  120. <SwiperSlide style={{ width: "100%" }}>
  121. <section className="relative h-[100%]" ref={homeContainerRef}>
  122. {children}
  123. </section>
  124. </SwiperSlide>
  125. </Swiper>
  126. </div>
  127. );
  128. };
  129. export const Providers = ({ children, themeProps }: ProvidersProps) => {
  130. useDebounceEffect(() => {
  131. if ("serviceWorker" in navigator) {
  132. initFirebase();
  133. }
  134. }, []);
  135. return (
  136. <ConfigProvider locale={enUS}>
  137. <Layout>{children}</Layout>
  138. </ConfigProvider>
  139. );
  140. };